home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C / Applications / Python 1.3.3 / Python 133 SRC / Extensions / img / imgpbmmodule.c < prev    next >
Text File  |  1995-12-21  |  13KB  |  545 lines

  1. /***********************************************************
  2. Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
  3. Amsterdam, The Netherlands.
  4.  
  5.                         All Rights Reserved
  6.  
  7. Permission to use, copy, modify, and distribute this software and its 
  8. documentation for any purpose and without fee is hereby granted, 
  9. provided that the above copyright notice appear in all copies and that
  10. both that copyright notice and this permission notice appear in 
  11. supporting documentation, and that the names of Stichting Mathematisch
  12. Centrum or CWI not be used in advertising or publicity pertaining to
  13. distribution of the software without specific, written prior permission.
  14.  
  15. STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
  16. THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
  17. FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
  18. FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  19. WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  20. ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
  21. OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  22.  
  23. ******************************************************************/
  24.  
  25. #include "Python.h"
  26. #include "import.h"
  27. #include "pbm.h"
  28.  
  29. /* The image formats we support */
  30. static PyObject *format_pbm, *format_choices;
  31. extern PyObject *getimgformat();    /* Get format by name */
  32.  
  33. /*
  34. ** Since PBMPLUS error handling is abysmal (print message, exit),
  35. ** there is a modified version that has (slightly) better error
  36. ** handling. Contact jack@cwi.nl if you want it. Define PBMNEWERROR
  37. ** if you have the modified pbmplus.
  38. **
  39. ** If you don't have it the first pbm error will abort you python
  40. ** program.
  41. */
  42. #define PBMNEWERROR
  43.  
  44. #ifndef PBMNEWERROR
  45. #define PBM_END
  46. #define PBM_START if (0) {
  47. #define PBM_ENDSTART }
  48.  
  49. #else
  50.  
  51. #include <setjmp.h>
  52. jmp_buf pbmerrenv;
  53. char pbmerrstr[1000];
  54.  
  55. #define PBM_END pm_setmsghandler(0); pm_setexithandler(0);
  56. #define PBM_START if ( setjmp(pbmerrenv) != 0 ) { \
  57.         PyErr_SetString(errobject, pbmerrstr); \
  58.     *pbmerrstr = '\0'; \
  59.         PBM_END
  60. #define PBM_ENDSTART return 0; \
  61.     } \
  62.     pm_setmsghandler(my_pmerr); \
  63.     pm_setexithandler(my_pmexit);
  64.  
  65.  
  66. static void
  67. my_pmerr(str)
  68.     char *str;
  69. {
  70.     strncpy(pbmerrstr, str, 999);
  71. }
  72.  
  73. static void
  74. my_pmexit()
  75. {
  76.     longjmp(pbmerrenv, 1);
  77. }
  78.  
  79. #endif /* PBMNEWERROR */
  80.  
  81. /* Pbm objects */
  82.  
  83. typedef struct {
  84.     PyObject_HEAD
  85.     PyObject    *dict;        /* Attributes dictionary */
  86.     int    is_reader;    /* TRUE if this is a reader */
  87.     char    *filename;    /* filename of the image file */
  88.     FILE    *filep;
  89.     int    format;
  90. } pbmobject;
  91.  
  92. static PyObject *errobject;
  93.  
  94. staticforward PyTypeObject Pbmtype;
  95.  
  96. #define is_pbmobject(v)        ((v)->ob_type == &Pbmtype)
  97.  
  98. static char doc_pbm[] = "This object reads/writes PBM files\n"
  99.     "The 'width', 'height' and 'format' attributes describe the picture\n"
  100.     "For writers, setting 'forceplain' creates an ASCII PBM file.";
  101.  
  102. /* Routine to easily obtain C data from the dict python data */
  103. int
  104. pbmselfattr(self, name, fmt, ptr, wanterr)
  105.     pbmobject *self;
  106.     char *name;
  107.     char *fmt;
  108.     void *ptr;
  109.     int wanterr;
  110. {
  111.     PyObject *obj;
  112.     char errbuf[100];
  113.  
  114.     obj = PyDict_GetItemString(self->dict, name);
  115.     if ( obj == NULL ) {
  116.     if ( wanterr ) {
  117.         sprintf(errbuf, "Required attribute '%s' not set", name);
  118.         PyErr_SetString(errobject, errbuf);
  119.         return 0;
  120.     } else {
  121.         PyErr_Clear();
  122.         return 0;
  123.     }
  124.     }
  125.     if ( !PyArg_Parse(obj, fmt, ptr) ) {
  126.     if ( !wanterr )
  127.         PyErr_Clear();
  128.     return 0;
  129.     }
  130.     return 1;
  131. }
  132.  
  133. /* Routine to easily insert integer into dictionary */
  134. pbmsetintattr(self, name, value)
  135.     pbmobject *self;
  136.     char *name;
  137.     int value;
  138. {
  139.     PyObject *obj;
  140.     int rv;
  141.  
  142.     obj = PyInt_FromLong(value);
  143.     rv = PyDict_SetItemString(self->dict, name, obj);
  144.     Py_DECREF(obj);
  145.     return rv;
  146. }
  147.  
  148. static pbmobject *
  149. newpbmobject()
  150. {
  151.     pbmobject *xp;
  152.     xp = PyObject_NEW(pbmobject, &Pbmtype);
  153.     if (xp == NULL)
  154.         return NULL;
  155.     xp->dict = PyDict_New();
  156.     xp->filename = NULL;
  157.     xp->filep = NULL;
  158.     return xp;
  159. }
  160.  
  161. static int
  162. initpbmreader(self, name)
  163.     pbmobject *self;
  164.     char *name;
  165. {
  166.     char *name_copy;
  167.     int cols, rows;
  168.  
  169.     if( (name_copy=malloc(strlen(name)+1)) == NULL ) {
  170.     PyErr_NoMemory();
  171.     return 0;
  172.     }
  173.     strcpy(name_copy, name);
  174.     self->filename = name_copy;
  175.     self->is_reader = 1;
  176.  
  177.     if ((self->filep = fopen(self->filename, "rb")) == NULL ) {
  178.     PyErr_SetFromErrno(PyExc_IOError);
  179.     return 0;
  180.     }
  181.     PBM_START
  182.     fclose(self->filep);
  183.         self->filep = 0;
  184.     return 0;
  185.     PBM_ENDSTART
  186.     pbm_readpbminit(self->filep, &cols, &rows, &self->format);
  187.     PBM_END
  188.  
  189.     pbmsetintattr(self, "width", cols);
  190.     pbmsetintattr(self, "height", rows);
  191.     PyDict_SetItemString(self->dict, "format", format_pbm);
  192.     PyDict_SetItemString(self->dict, "format_choices", format_choices);
  193.     if ( PyErr_Occurred() )
  194.     return 0;
  195.     return 1;
  196. }
  197.  
  198. static int
  199. initpbmwriter(self, name)
  200.     pbmobject *self;
  201.     char *name;
  202. {
  203.     char *name_copy;
  204.  
  205.     if( (name_copy=malloc(strlen(name)+1)) == NULL ) {
  206.     PyErr_NoMemory();
  207.     return 0;
  208.     }
  209.     strcpy(name_copy, name);
  210.     self->filename = name_copy;
  211.     self->filep = NULL;
  212.     self->is_reader = 0;
  213.     PyDict_SetItemString(self->dict, "format", format_pbm);
  214.     PyDict_SetItemString(self->dict, "format_choices", format_choices);
  215.     if( PyErr_Occurred())
  216.     return 0;
  217.     return 1;
  218. }
  219.  
  220. /* Pbm methods */
  221.  
  222. static void
  223. pbm_dealloc(xp)
  224.     pbmobject *xp;
  225. {
  226.     Py_XDECREF(xp->dict);
  227.     if( xp->filename )
  228.         free(xp->filename);
  229.     if( xp->filep )
  230.         fclose(xp->filep);
  231.     PyMem_DEL(xp);
  232. }
  233.  
  234. static char doc_read[] = "Read the actual data, returns a string";
  235.  
  236. static PyObject *
  237. pbm_read(self, args)
  238.     pbmobject *self;
  239.     PyObject *args;
  240. {
  241.         int i, w, h, rowlen;
  242.     PyObject *rv;
  243.     char *datap;
  244.     bit *pixelrow;
  245.     PyObject *fmt;
  246.     
  247.     if (!PyArg_ParseTuple(args,""))
  248.         return NULL;
  249.     if (!self->is_reader) {
  250.         PyErr_SetString(errobject, "Cannot read() from writer object");
  251.         return NULL;
  252.     }
  253.     /* XXXX Read data and return it */
  254.     /* XXXX Get args from self->dict and write the data */
  255.     if ( !pbmselfattr(self, "width", "i", &w, 1) ||
  256.          !pbmselfattr(self, "height", "i", &h, 1) ||
  257.          !pbmselfattr(self, "format", "O", &fmt, 1) )
  258.         return NULL;
  259.     if ( fmt != format_pbm ) {
  260.         PyErr_SetString(errobject, "Unsupported image format");
  261.         return NULL;
  262.     }
  263.     pixelrow = 0;
  264.     rv = 0;
  265.     PBM_START
  266.         if ( pixelrow )
  267.         pbm_freerow(pixelrow);
  268.         if ( rv )
  269.         Py_DECREF(rv);
  270.         return NULL;
  271.     PBM_ENDSTART
  272.  
  273.     rowlen = w;
  274.     pixelrow=pbm_allocrow(w);
  275.  
  276.     if ( (rv=PyString_FromStringAndSize(0, rowlen*h)) == NULL ) {
  277.         pbm_freerow(pixelrow);
  278.         return NULL;
  279.     }
  280.     datap = PyString_AsString(rv);
  281.  
  282.     while( h > 0 ) {
  283.         pbm_readpbmrow(self->filep, pixelrow, w, self->format);
  284.         for(i=0; i<w; i++)
  285.         datap[i] = pixelrow[i];
  286.         datap += rowlen;
  287.         h -= 1;
  288.     }
  289.         PBM_END
  290.     pbm_freerow(pixelrow);
  291.     return rv;
  292. }
  293.  
  294. static char doc_write[] = "Write (string) data to the PBM file";
  295.  
  296. static PyObject *
  297. pbm_write(self, args)
  298.     pbmobject *self;
  299.     PyObject *args;
  300. {
  301.         unsigned char *data;
  302.     int datalen;
  303.     int i, w, h, rowlen;
  304.     PyObject *fmt;
  305.     bit *pixelrow;
  306.     int forceplain;
  307.     FILE *filep;
  308.     
  309.     if (!PyArg_ParseTuple(args, "s#", &data, &datalen))
  310.         return NULL;
  311.     if (self->is_reader) {
  312.         PyErr_SetString(errobject, "Cannot write() to reader object");
  313.         return NULL;
  314.     }
  315.     /* XXXX Get args from self->dict and write the data */
  316.     if ( !pbmselfattr(self, "width", "i", &w, 1) ||
  317.          !pbmselfattr(self, "height", "i", &h, 1) ||
  318.          !pbmselfattr(self, "format", "O", &fmt, 1) )
  319.         return NULL;
  320.  
  321.     forceplain = 0;
  322.     pbmselfattr(self, "forceplain", "i", &forceplain, 0);
  323.  
  324.     rowlen = w;
  325.     
  326.     if ( fmt != format_pbm ) {
  327.         PyErr_SetString(errobject, "Unsupported image format");
  328.         return NULL;
  329.     }
  330.  
  331.     if( rowlen*h != datalen ) {
  332.         PyErr_SetString(errobject, "Incorrect datasize");
  333.         return NULL;
  334.     }
  335.  
  336.     if ((filep = fopen(self->filename, forceplain?"w":"wb")) == NULL) {
  337.         PyErr_SetFromErrno(PyExc_IOError);
  338.         return 0;
  339.     }
  340. #ifdef macintosh
  341.     setfiletype(self->filename, '????', 'PPBM');
  342. #endif
  343.  
  344.     pixelrow = 0;
  345.     PBM_START
  346.         if ( pixelrow )
  347.         pbm_freerow(pixelrow);
  348.         fclose(filep);
  349.         return NULL;
  350.     PBM_ENDSTART
  351.  
  352.     pixelrow=pbm_allocrow(w);
  353.  
  354.     pbm_writepbminit(filep, w, h, forceplain);
  355.     while( h > 0 ) {
  356.         for(i=0; i<w; i++)
  357.         pixelrow[i] = data[i];
  358.         pbm_writepbmrow(filep, pixelrow, w, forceplain);
  359.         data += rowlen;
  360.         h -= 1;
  361.     }
  362.     PBM_END
  363.     pbm_freerow(pixelrow);
  364.     if (fclose(filep) != 0) {
  365.         PyErr_SetFromErrno(PyExc_IOError);
  366.         return NULL;
  367.     }
  368.     Py_INCREF(Py_None);
  369.     return Py_None;
  370. }
  371.  
  372. static struct PyMethodDef pbm_methods[] = {
  373.     {"read",    (PyCFunction)pbm_read,    1,    doc_read},
  374.     {"write",    (PyCFunction)pbm_write,    1,    doc_write},
  375.     {NULL,        NULL}        /* sentinel */
  376. };
  377.  
  378. static PyObject *
  379. pbm_getattr(xp, name)
  380.     pbmobject *xp;
  381.     char *name;
  382. {
  383.         PyObject *v;
  384.     
  385.     if (xp->dict != NULL) {
  386.             if ( strcmp(name, "__dict__") == 0 ) {
  387.                 Py_INCREF(xp->dict);
  388.             return xp->dict;
  389.         }
  390.                if ( strcmp(name, "__doc__") == 0 ) {
  391.                 return PyString_FromString(doc_pbm);
  392.         }
  393.         v = PyDict_GetItemString(xp->dict, name);
  394.         if (v != NULL) {
  395.             Py_INCREF(v);
  396.             return v;
  397.         }
  398.     }
  399.     return Py_FindMethod(pbm_methods, (PyObject *)xp, name);
  400. }
  401.  
  402. static int
  403. pbm_setattr(xp, name, v)
  404.     pbmobject *xp;
  405.     char *name;
  406.     PyObject *v;
  407. {
  408.     if (xp->dict == NULL) {
  409.         xp->dict = PyDict_New();
  410.         if (xp->dict == NULL)
  411.             return -1;
  412.     }
  413.     if (v == NULL) {
  414.         int rv = PyDict_DelItemString(xp->dict, name);
  415.         if (rv < 0)
  416.             PyErr_SetString(PyExc_AttributeError,
  417.                     "delete non-existing imgpbm attribute");
  418.         return rv;
  419.     }
  420.     else
  421.         return PyDict_SetItemString(xp->dict, name, v);
  422. }
  423.  
  424. static PyTypeObject Pbmtype = {
  425.     PyObject_HEAD_INIT(&PyType_Type)
  426.     0,            /*ob_size*/
  427.     "imgpbm",        /*tp_name*/
  428.     sizeof(pbmobject),    /*tp_basicsize*/
  429.     0,            /*tp_itemsize*/
  430.     /* methods */
  431.     (destructor)pbm_dealloc, /*tp_dealloc*/
  432.     0,            /*tp_print*/
  433.     (getattrfunc)pbm_getattr, /*tp_getattr*/
  434.     (setattrfunc)pbm_setattr, /*tp_setattr*/
  435.     0,            /*tp_compare*/
  436.     0,            /*tp_repr*/
  437.     0,            /*tp_as_number*/
  438.     0,            /*tp_as_sequence*/
  439.     0,            /*tp_as_mapping*/
  440.     0,            /*tp_hash*/
  441. };
  442.  
  443. static char doc_newreader[] =
  444.     "Return an object that reads the PBM/PBM file passed as argument";
  445.  
  446. static PyObject *
  447. pbm_newreader(self, args)
  448.     PyObject *self;
  449.     PyObject *args;
  450. {
  451.         char *filename;
  452.     pbmobject *obj;
  453.     
  454.     if (!PyArg_ParseTuple(args, "s", &filename))
  455.         return NULL;
  456.     if ((obj = newpbmobject()) == NULL)
  457.         return NULL;
  458.     if ( !initpbmreader(obj, filename) ) {
  459.         pbm_dealloc(obj);
  460.         return NULL;
  461.     }
  462.     return (PyObject *)obj;
  463. }
  464.  
  465. static char doc_newwriter[] =
  466.     "Return an object that writes the PBM file passed as argument";
  467.  
  468. static PyObject *
  469. pbm_newwriter(self, args)
  470.     PyObject *self;
  471.     PyObject *args;
  472. {
  473.         char *filename;
  474.     pbmobject *obj;
  475.     
  476.     if (!PyArg_ParseTuple(args, "s", &filename))
  477.         return NULL;
  478.     if ((obj = newpbmobject()) == NULL)
  479.         return NULL;
  480.     if ( !initpbmwriter(obj, filename) ) {
  481.         pbm_dealloc(obj);
  482.         return NULL;
  483.     }
  484.     return (PyObject *)obj;
  485. }
  486.  
  487.  
  488. /* List of functions defined in the module */
  489.  
  490. static struct PyMethodDef pbm_module_methods[] = {
  491.     {"reader",    pbm_newreader,    1,    doc_newreader},
  492.     {"writer",    pbm_newwriter,    1,    doc_newwriter},
  493.     {NULL,        NULL}        /* sentinel */
  494. };
  495.  
  496.  
  497. /* Initialization function for the module (*must* be called initimgpbm) */
  498. static char doc_imgpbm[] =
  499.   "Module that reads images from PBM files writes them too.";
  500.  
  501.  
  502. void
  503. initimgpbm()
  504. {
  505.     PyObject *m, *d, *x, *formatmodule, *formatdict;
  506.  
  507.     /* Create the module and add the functions */
  508.     m = Py_InitModule("imgpbm", pbm_module_methods);
  509.  
  510.     /* Add some symbolic constants to the module */
  511.     d = PyModule_GetDict(m);
  512.     errobject = PyString_FromString("imgpbm.error");
  513.     PyDict_SetItemString(d, "error", errobject);
  514.     x = PyString_FromString(doc_imgpbm);
  515.     PyDict_SetItemString(d, "__doc__", x);
  516.  
  517.     /* Get supported formats */
  518.     if ((formatmodule = PyImport_ImportModule("imgformat")) == NULL)
  519.         Py_FatalError("imgpbm depends on imgformat");
  520.     if ((formatdict = PyModule_GetDict(formatmodule)) == NULL)
  521.         Py_FatalError("imgformat has no dict");
  522.  
  523.     format_pbm = PyDict_GetItemString(formatdict,"pbmbitmap");
  524.     format_choices = Py_BuildValue("(O)", format_pbm);
  525.  
  526.     /* Initialize pbmplus */
  527.         {
  528.         int pbm_argc;
  529.         static char *pbm_arglist[] = { "pbmplus", 0};
  530.         char **pbm_argv;
  531.  
  532.         pbm_argc = 1;
  533.         pbm_argv = pbm_arglist;
  534.         PBM_START /* { */
  535.         Py_FatalError("pbmplus initialization error");
  536.         } /* PBM_ENDSTART won't work here, it has return NULL */
  537.         pbm_init(&pbm_argc, pbm_argv);
  538.         PBM_END
  539.     }
  540.  
  541.     /* Check for errors */
  542.     if (PyErr_Occurred())
  543.         Py_FatalError("can't initialize module imgpbm");
  544. }
  545.